package com.awan.utils.android.image;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.Stack;
import java.util.WeakHashMap;

import com.beem.project.beem.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader.TileMode;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.ImageView.ScaleType;



public class ImageLoader {
    
    MemoryCache memoryCache=new MemoryCache();
    FileCache fileCache;
    Context ctx;
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    
    public ImageLoader(Context context){
    	ctx=context;
    	//Make the background thead low priority. This way it will not affect the UI performance
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
        
        fileCache=new FileCache(context);
    }
    
    final int stub_id=R.drawable.beem_launcher_icon_silver;
     ProgressBar pb;
    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
    /*	pb=(ProgressBar)imageView.findViewById(R.id.progressBar1);
    	pb.setVisibility(View.VISIBLE);*/
    	//imageView.setImageResource(R.drawable.curve);
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
       // imageView.setImageResource(R.drawable.curve);
        if(bitmap!=null){
        	//imageView.setImageResource(bitmap);
        	// imageView.setImageResource(R.drawable.curve);
        	//imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
        	Bitmap bRef=getRefelection(bitmap);
          imageView.setImageBitmap(bRef);
          imageView.setScaleType(ScaleType.FIT_XY);
         // LinearLayout linLayout = new LinearLayout(activity);
         // linLayout.addView(imageView,   new LinearLayout.LayoutParams(   LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT                  )            );
             
           // set LinearLayout as ContentView
          //activity.setContentView(linLayout);
          // imageView.setScaleType(ScaleType.CENTER);
        }
        else
        {
        	//progressBar1
            queuePhoto(url, activity, imageView);
           // Bitmap bRef=getRefelection(stub_id);
            Bitmap bmp=BitmapFactory.decodeResource(activity.getResources(), stub_id);
            Bitmap bRef=getRefelection(bmp);
            imageView.setImageBitmap(bRef);
            //imageView.setImageResource(bRef);
          //imageView.setScaleType(ScaleType.CENTER);
           // imageView.setBackgroundResource(R.drawable.metroicon);
           /* imageView.setImageResource(stub_id);
            imageView.setScaleType(ScaleType.FIT_XY);*/
        }    
    }
  
    public void DisplayImageDrawable(String url, Activity activity, ImageView imageView)
    {
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
         
        if(bitmap!=null){
        	//imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
            imageView.setImageBitmap(bitmap);
            imageView.setScaleType(ScaleType.CENTER);
        }
        else
        {
        	//imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
            queuePhoto(url, activity, imageView);
           imageView.setImageResource(stub_id);
           imageView.setScaleType(ScaleType.CENTER);
        }    
    }
        
    private void queuePhoto(String url, Activity activity, ImageView imageView)
    {
        //This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them. 
        photosQueue.Clean(imageView);
        PhotoToLoad p=new PhotoToLoad(url, imageView);
        synchronized(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
            
        }
        
        //start thread if it's not started yet
        if(photoLoaderThread.getState()==Thread.State.NEW)
            photoLoaderThread.start();
    }
    
   
    private Bitmap getBitmap(String url) 
    {
        File f=fileCache.getFile(url);
        InputStream is;
        OutputStream os;
        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;
        
        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            if(conn.getErrorStream() == null){
            	 /*is=conn.getInputStream();
                 os = new FileOutputStream(f);*/
            	Log.e("stream Error","err stream== null");
            }else{
            	Log.e("stream Error","err stream");
            	 AlertDialog.Builder alertbox = new AlertDialog.Builder(ctx);

                 // Set the message to display
                 alertbox.setMessage("This is an alert box.");

                 // Add a neutral button to the alert box and assign a click listener
                 alertbox.setNeutralButton("Ok", new DialogInterface.OnClickListener() {

                     // Click listener on the neutral button of alert box
                     public void onClick(DialogInterface arg0, int arg1) {

                         // The neutral button was clicked
                         //Toast.makeText(getApplicationContext(), "'OK' button clicked", Toast.LENGTH_LONG).show();
                     }
                     });
            }
            is=conn.getInputStream();
            os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
           BitmapFactory.decodeStream(new FileInputStream(f),null,o);
            
            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }
            
            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            Bitmap b=BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
            //Drawable d = new BitmapDrawable(b);
            int h = 210 ;// height in pixels
            int w = 300; // width in pixels    
           // Bitmap scaled = Bitmap.createScaledBitmap(b, h, w, true);

            return b;
        } catch (FileNotFoundException e) {return null;}
    	//
    	/*try {
            final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
           InputStream in = new FileInputStream(f);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, o);
            in.close();



            int scale = 1;
            while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) {
                scale++;
            }
            Log.d("Image Loader ", "scale = " + scale + ", orig-width: " + o.outWidth       + ", orig-height: " + o.outHeight);

            Bitmap b = null;
           // in = mContentResolver.openInputStream(uri);
            if (scale > 1) {
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                o = new BitmapFactory.Options();
                o.inSampleSize = scale;
                b = BitmapFactory.decodeStream(in, null, o);

                // resize to desired dimensions
                int height = b.getHeight();
                int width = b.getWidth();
                Log.d("Image Loader ", "1th scale operation dimenions - width: " + width    + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,     (int) y, true);
                b.recycle();
                b = scaledBitmap;

                System.gc();
            } else {
                b = BitmapFactory.decodeStream(in);
            }
            in.close();

            //Log.d("Image Loader ", "bitmap size - width: " +b.getWidth() + ", height: " + b.getHeight());
            return b;
        } catch (IOException e) {
            Log.e("Image Loader ", e.getMessage(),e);
            return null;
        }*/
    	
    	
    }
    

    //Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public PhotoToLoad(String u, ImageView i){
            url=u; 
            imageView=i;
        }
    }
    
    PhotosQueue photosQueue=new PhotosQueue();
    
    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }
    
    //stores list of photos to download
    class PhotosQueue
    {
        private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
        
        //removes all instances of this ImageView
        public void Clean(ImageView image)
        {
            for(int j=0 ;j<photosToLoad.size();){
                if(photosToLoad.get(j).imageView==image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        }
    }
    
    class PhotosLoader extends Thread {
        @Override
		public void run() {
            try {
                while(true)
                {
                    //thread waits until there are any images to load in the queue
                    if(photosQueue.photosToLoad.size()==0)
                        synchronized(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    if(photosQueue.photosToLoad.size()!=0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized(photosQueue.photosToLoad){
                            photoToLoad=photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp=getBitmap(photoToLoad.url);
                        memoryCache.put(photoToLoad.url, bmp);
                        String tag=imageViews.get(photoToLoad.imageView);
                        if(tag!=null && tag.equals(photoToLoad.url)){
                            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
                            Activity a=(Activity)photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if(Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e) {
                //allow thread to exit
            }
        }
    }
    
    PhotosLoader photoLoaderThread=new PhotosLoader();
    
    //Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap; Bitmap bref;
        ImageView imageView;
        public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
        public void run()
        {
            if(bitmap!=null){
            bref=getRefelection(bitmap);
             imageView.setImageBitmap(bref);
           // imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
            }
            else{
            	
            	//imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
            	imageView.setImageResource(stub_id);
            }
               
        }
    }

    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }

    
    //reflection image
    public Bitmap getRefelection(Bitmap image)
    {
      //The gap we want between the reflection and the original image
        final int reflectionGap = 4;//4
      
        //Get you bit map from drawable folder
        Bitmap originalImage = image ;
      
    
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();
      
    
        //This will not scale but will flip on the Y axis
        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);
      
        //Create a Bitmap with the flip matix applied to it.
        //We only want the bottom half of the image
        Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/3, width, height/3, matrix, false);
      
          
        //Create a new bitmap with same width but taller to fit reflection
        Bitmap bitmapWithReflection = Bitmap.createBitmap(width
          , (height + height/3), Config.ARGB_8888);
    
       //Create a new Canvas with the bitmap that's big enough for
       //the image plus gap plus reflection
       Canvas canvas = new Canvas(bitmapWithReflection);
       //Draw in the original image
       canvas.drawBitmap(originalImage, 0, 0, null);
       //Draw in the gap
       Paint deafaultPaint = new Paint();
       canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
       //Draw in the reflection
       canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
    
       //Create a shader that is a linear gradient that covers the reflection
       Paint paint = new Paint();
       LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
         bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
         TileMode.CLAMP);
       //Set the paint to use this shader (linear gradient)
       paint.setShader(shader);
       //Set the Transfer mode to be porter duff and destination in
     // paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN))
       paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
       //Draw a rectangle using the paint with our linear gradient
       canvas.drawRect(0, height, width,
         bitmapWithReflection.getHeight() + reflectionGap, paint);
       return bitmapWithReflection;
    }
}
